#include "Conversor.h"
#include "../modelo/Objetos/Dinamicos/ObjetoDinamico.h"
#include "../modelo/Objetos/Estaticos/ObjetoEstatico.h"
#include "../modelo/Objetos/Dinamicos/Huevo.h"
#include "../modelo/Objetos/Dinamicos/HuevoNegro.h"
#include "../modelo/Objetos/Dinamicos/Pajaro.h"
#include "../modelo/Objetos/Dinamicos/Pollo.h"
#include "../modelo/Objetos/Dinamicos/Cuervo.h"
#include "../modelo/Objetos/Estaticos/Fondo.h"
#include "../modelo/Objetos/Estaticos/Fondo2.h"
#include "../modelo/Objetos/Estaticos/FondoSimpsons.h"
#include "../modelo/Objetos/Estaticos/Nido.h"
#include "../modelo/Objetos/Estaticos/Monticulo.h"
#include "../modelo/Objetos/Estaticos/Caja.h"
#include "../modelo/Objetos/Estaticos/CajaMetal.h"
#include "../modelo/Objetos/Estaticos/Banana.h"
#include "../modelo/Objetos/Estaticos/Manzana.h"
#include "../modelo/Objetos/Estaticos/Piso.h"
#include "../modelo/Objetos/Estaticos/Cerdo.h"
#include "../modelo/Objetos/Estaticos/Catapulta.h"
#include "../modelo/Objetos/Estaticos/Reloj.h"
#include "../modelo/Auxiliares/Velocidad.h"
#include <typeinfo>
#include <sstream>
#include <iostream>
Conversor::~Conversor() {
}

//        I partida inicia
//        G get partidas
//        W partida ganada
//        P partida perdida
std::string Conversor::serializar(char p){
	std::string ret;
	ret +=p;
	ret = cargarShort(ret, 0);
	return ret;
}

//  P partidas
std::string Conversor::serializar(std::vector<PartidaMultijugador*> *partidas) {
	
	std::string ret;
	ret +="P";
	ret = cargarShort(ret, partidas->size()*3);
	for (size_t i = 0; i < partidas->size(); i++) {
		short id = (*partidas)[i]->getId();
		short libres = (*partidas)[i]->getLugaresLibres();
		short nivel = (*partidas)[i]->getCodigoNivel();
		ret = cargarShort(ret, id);
		ret = cargarShort(ret, libres);
		ret = cargarShort(ret, nivel);
	}
	return ret;
}
//		B baja objeto 
// 		U unirse a partida
std::string Conversor::serializar(char p,short id){
	std::string ret;
	ret +=p;
	ret = cargarShort(ret, 1);
	ret = cargarShort(ret, id);
	return ret;
}

// L : lanzar huevo (cliente->servidor)
// C : crear partida jugadores nivel
std::string Conversor::serializar(char op, short vx, short vy) {
	std::string ret;
	ret +=op;
	ret = cargarShort(ret, 2);
	ret = cargarShort(ret, vx);
	ret = cargarShort(ret, vy);
	return ret;
}

// A : add objeto
std::string Conversor::serializar(Objeto *obj) {
	std::string ret;
	ret +="A";
	ret = cargarShort(ret, 7);

	if (typeid(*obj) == typeid(Huevo)){
		ret += "Huev";		
		short vx = ((ObjetoDinamico*)obj)->getVelocidadInstX();
		short vy = ((ObjetoDinamico*)obj)->getVelocidadInstY();
		ret = cargarShort(ret, vx);
		ret = cargarShort(ret, vy);
	}
	if (typeid(*obj) == typeid(HuevoNegro)){
		ret += "Huen";
		short vx = ((ObjetoDinamico*)obj)->getVelocidadInstX();
		short vy = ((ObjetoDinamico*)obj)->getVelocidadInstY();
		ret = cargarShort(ret, vx);
		ret = cargarShort(ret, vy);
	}
	if (typeid(*obj) == typeid(Pajaro)){
		ret += "Paja";
		short vx = ((ObjetoDinamico*)obj)->getVelocidadInstX();
		short vy = ((ObjetoDinamico*)obj)->getVelocidadInstY();
		ret = cargarShort(ret, vx);
		ret = cargarShort(ret, vy);
	}
	if (typeid(*obj) == typeid(Pollo)){
		ret += "Poll";
		short vx = ((ObjetoDinamico*)obj)->getVelocidadInstX();
		short vy = ((ObjetoDinamico*)obj)->getVelocidadInstY();
		ret = cargarShort(ret, vx);
		ret = cargarShort(ret, vy);
	}
	if (typeid(*obj) == typeid(Cuervo)){
		ret += "Cuer";
		short vx = ((ObjetoDinamico*)obj)->getVelocidadInstX();
		short vy = ((ObjetoDinamico*)obj)->getVelocidadInstY();
		ret = cargarShort(ret, vx);
		ret = cargarShort(ret, vy);
	}
	if (typeid(*obj) == typeid(Monticulo)){
		ret += "Mont";
		ret = cargarShort(ret, 1);
		ret = cargarShort(ret, 1);
	}
	if (typeid(*obj) == typeid(Nido)){
		ret += "Nido";
		ret = cargarShort(ret, 1);
		ret = cargarShort(ret, 1);
	}
	if (typeid(*obj) == typeid(Fondo)){
		ret += "Fond";
		ret = cargarShort(ret, 1);
		ret = cargarShort(ret, 1);
	}
	if (typeid(*obj) == typeid(Fondo2)){
		ret += "Fon2";
		ret = cargarShort(ret, 1);
		ret = cargarShort(ret, 1);
	}
	if (typeid(*obj) == typeid(FondoSimpsons)){
		ret += "Fons";
		ret = cargarShort(ret, 1);
		ret = cargarShort(ret, 1);
	}
	if (typeid(*obj) == typeid(Caja)){
		ret += "Caja";
		ret = cargarShort(ret, 1);
		ret = cargarShort(ret, 1);
	}
	if (typeid(*obj) == typeid(CajaMetal)){
		ret += "Cajm";
		ret = cargarShort(ret, 1);
		ret = cargarShort(ret, 1);
	}
	if (typeid(*obj) == typeid(Manzana)){
		ret += "Manz";
		ret = cargarShort(ret, 1);
		ret = cargarShort(ret, 1);
	}
	if (typeid(*obj) == typeid(Banana)){
		ret += "Bana";
		ret = cargarShort(ret, 1);
		ret = cargarShort(ret, 1);
	}
	if (typeid(*obj) == typeid(Piso)){
		ret += "Piso";
		ret = cargarShort(ret, 1);
		ret = cargarShort(ret, 1);
	}
	if (typeid(*obj) == typeid(Cerdo)){
		ret += "Cerd";
		ret = cargarShort(ret, 1);
		ret = cargarShort(ret, 1);
	}
	if (typeid(*obj) == typeid(Catapulta)){
		ret += "Cata";
		ret = cargarShort(ret, 1);
		ret = cargarShort(ret, 1);
	}
	if (typeid(*obj) == typeid(Reloj)){
		ret += "Relo";
		ret = cargarShort(ret,((Reloj*)obj)->getTiempoMilisec());
		ret = cargarShort(ret, 1);
	}
	ret = cargarShort(ret, obj->getX());
	ret = cargarShort(ret, obj->getY());
	ret = cargarShort(ret, obj->getId());
	return ret;
}

std::vector<short> Conversor::deSerializar(std::string str){
	std::vector<short> ret;	
	if (str.size() > 3){
		short i = 1;
		short cantidadEsperada = 0;

			short numero = 0;
			char * paux = (char*)&numero;
			*paux++ = str.c_str()[i++];
			*paux = str.c_str()[i++];			
			 cantidadEsperada = numero;

		size_t numeros = 0;
		while (numeros < cantidadEsperada) {
			numero = 0;
			char * paux = (char*)&numero;
			*paux++ = str.c_str()[i++];
			*paux = str.c_str()[i++];
			numeros++;
			ret.push_back(numero);
		}
	}
	return ret;	
}

Objeto *Conversor::deSerializarObjeto(std::string str) {
	std::string tipo = str.substr(3,4);
		
	std::string parametros = "A";
	parametros = cargarShort(parametros, 5);
	parametros += str.substr(7,str.size()-7);
	std::vector<short> vec= deSerializar(parametros);
	
	Objeto* obj;
	if ("Huev" == tipo){
		obj = new Huevo(vec[2],vec[3],new Velocidad(vec[0],vec[1]),NULL);
		obj->setId(vec[4]);
	}
	if ("Huen" == tipo){
		obj = new HuevoNegro(vec[2],vec[3],new Velocidad(vec[0],vec[1]),NULL);
		obj->setId(vec[4]);
	}
	if ("Paja" == tipo){
		obj = new Pajaro(vec[2],vec[3],new Velocidad(vec[0],vec[1]));
		obj->setId(vec[4]);
	}
	if ("Cuer" == tipo){
		obj = new Cuervo(vec[2],vec[3],new Velocidad(vec[0],vec[1]));
		obj->setId(vec[4]);
	}
	if ("Poll" == tipo){
		obj = new Pollo(vec[2],vec[3],new Velocidad(vec[0],vec[1]));
		obj->setId(vec[4]);
	}
	if ("Caja" == tipo){
		obj = new Caja(vec[2],vec[3]);
		obj->setId(vec[4]);
	}
	if ("Cajm" == tipo){
		obj = new CajaMetal(vec[2],vec[3]);
		obj->setId(vec[4]);
	}
	if ("Bana" == tipo){
		obj = new Banana(vec[2],vec[3]);
		obj->setId(vec[4]);
	}
	if ("Manz" == tipo){
		obj = new Manzana(vec[2],vec[3]);
		obj->setId(vec[4]);
	}
	if ("Piso" == tipo){
		obj = new Piso();
		obj->setId(vec[4]);
	}
	if ("Cerd" == tipo){
		obj = new Cerdo(vec[2],vec[3]);
		obj->setId(vec[4]);
	}
	if ("Cata" == tipo){
		obj = new Catapulta(vec[2],vec[3]);
		obj->setId(vec[4]);
	}
	if ("Mont" == tipo){
		obj = new Monticulo(vec[2],vec[3]);
		obj->setId(vec[4]);
	}
	if ("Nido" == tipo){
		obj = new Nido(vec[2],vec[3],false);
		obj->setId(vec[4]);
	}
	if ("Fond" == tipo){
		obj = new Fondo();
		obj->setId(vec[4]);
	}
	if ("Fon2" == tipo){
		obj = new Fondo2();
		obj->setId(vec[4]);
	}
	if ("Fons" == tipo){
		obj = new FondoSimpsons();
		obj->setId(vec[4]);
	}
	if ("Relo" == tipo){
		obj = new Reloj(vec[0]);
		obj->setId(vec[4]);
	}
	return obj;
}

std::string Conversor::cargarShort(std::string str, short num) {
	char * pid = (char*)&(num);
	str += *pid++;
	str += *pid;
	return str;
}

std::string Conversor::shortToString(short n) {
	std::string s;
	std::stringstream out;
	out << n;
	s = out.str();
	return s;
}
/*
void Conversor::encolarComandos(std::queue<std::string> *q, std::string str) {
	std::string parcial = "";
	short numeros = 0;
	short posInicial = 0;
	for (size_t i = 0; i < str.size(); i++) {
		if ((str[posInicial] == 'A' && numeros < 15) || (str[posInicial] == 'B' && numeros < 3)
			|| ((str[posInicial] == 'W'||str[posInicial] == 'E') && numeros < 1)){
			parcial += str[i];
			numeros++;
		} else {
			parcial += str[i];
			q->push(parcial);
			parcial = "";
			numeros = 0;
			posInicial = i+1;
		}

	}
}*/
